home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / reve / xview.c < prev   
C/C++ Source or Header  |  1995-05-03  |  30KB  |  1,110 lines

  1. /*LINTLIBRARY*/
  2.  
  3. /*  @(#)xview.c 1.23 91/11/13
  4.  *
  5.  *  XView dependent graphics routines used by reve.
  6.  *
  7.  *  Copyright (c) 1990, 1991 - Rich Burridge & Yves Gallot.
  8.  *  All rights reserved.
  9.  *
  10.  *  Permission is granted to copy this source, for redistribution
  11.  *  in source form only, provided the news headers in "substantially
  12.  *  unaltered format" are retained, the introductory messages are not
  13.  *  removed, and no monies are exchanged.
  14.  *
  15.  *  Permission is also granted to copy this source, without the
  16.  *  news headers, for the purposes of making an executable copy by
  17.  *  means of compilation, provided that such copy will not be used
  18.  *  for the purposes of competition in any othello tournaments, without
  19.  *  prior permission from the authors.
  20.  *
  21.  *  No responsibility is taken for any errors or inaccuracies inherent
  22.  *  either to the comments or the code of this program, but if reported
  23.  *  (see README file), then an attempt will be made to fix them.
  24.  */
  25.  
  26. #include "reve.h"
  27. #include "color.h"
  28. #include "extern.h"
  29. #include "images.h"
  30. #include <ctype.h>
  31. #include <sys/ioctl.h>
  32. #include <sys/param.h>
  33. #include <sys/types.h>
  34. #include <sys/wait.h>
  35.  
  36. #include <xview/xview.h>
  37. #include <xview/canvas.h>
  38. #include <xview/panel.h>
  39. #include <xview/cms.h>
  40. #include <xview/cursor.h>
  41. #include <xview/svrimage.h>
  42. #include <xview/textsw.h>
  43. #include <xview/xv_xrect.h>
  44. #include <X11/Xlib.h>
  45. #include <X11/Xutil.h>
  46. #include <X11/Xresource.h>
  47.  
  48. #include "reve_ui.h"
  49.  
  50. #define  XV_SET             (void) xv_set
  51.  
  52. #define  CLIENT_NO          10
  53. #define  FRAME_BORDER_SIZE  7
  54. #define  FRAME_LABEL_SIZE   30
  55.  
  56. #define  BOARDFONT          "lucidasanstypewriter-10"
  57. #define  BOLDFONT           "lucidasanstypewriter-bold-12"
  58. #define  DEFFONT            "fixed"
  59. #define  HELPFONT           "lucidasanstypewriter-12"
  60. #define  NORMALFONT         "lucidasanstypewriter-12"
  61.  
  62. enum popup_pos { P_BELOW, P_RIGHT } ;  /* Positions relative to main frame. */
  63.  
  64. Canvas_paint_window gpw ;
  65. Event *cur_event ;
  66.  
  67. Notify_client client = (Notify_client) CLIENT_NO ;
  68.  
  69. reve_Wmain_objects  *Reve_Wmain ;
  70. reve_Wdepth_objects *Reve_Wdepth ;
  71. reve_Wprops_objects *Reve_Wprops ;
  72. reve_Whelp_objects  *Reve_Whelp ;
  73. reve_Wload_objects  *Reve_Wload ;
  74. reve_Wsave_objects  *Reve_Wsave ;
  75. reve_Wboard_objects *Reve_Wboard ;
  76.  
  77. Attr_attribute  INSTANCE ;
  78.  
  79. Server_image hglass_pr, nocur_pr ;
  80. Xv_Cursor cursor[MAXCURSORS] ;
  81.  
  82. Display *dpy ;                  /* Display id of reve frame. */
  83. Drawable images[MAXIMAGES] ;    /* Various graphics images used by reve. */
  84. Drawable xid ;                  /* Xid for reve canvas. */
  85. GC gc ;                         /* Graphics context for text and lines. */
  86. GC igc ;                        /* Graphics content for 1bit images. */
  87. GC ropgc ;                      /* Graphics context for rops. */
  88. GC stencilgc ;                  /* Graphics context for stencils. */
  89. Window root ;
  90. XFontStruct *font[MAXFONTS] ;   /* Xlib handles to the fonts. */
  91. XGCValues gc_val ;              /* Used to setup graphics context values. */
  92. XrmDatabase reve_DB ;           /* Combined resources database. */
  93.  
  94. int screen ;                    /* Default graphics display screen. */
  95. unsigned long backgnd ;         /* Default background color. */
  96. unsigned long foregnd ;         /* Default foreground color. */
  97. unsigned long gc_mask ;         /* Mask for setting graphic context values. */
  98. unsigned long palette[REVE_COLORSIZE] ;     /* Xlib color palette. */
  99.  
  100. int opvals[3] ;                 /* Graphics rasterop values. */
  101.  
  102. static Drawable make_server_image  P((unsigned char *)) ;
  103. static Notify_value check_clock    P((Notify_client, int)) ;
  104. static Notify_value quit_proc      P((Notify_client, Destroy_status)) ;
  105. static Notify_value read_from_fd   P((Notify_client, int)) ;
  106. static Notify_value sigchldcatcher P((Notify_client, int,
  107.                                       union wait *, struct rusage *)) ;
  108. static XFontStruct *get_font       P((char *, char *)) ;
  109.  
  110. Menu_item menu_do                  P((Menu_item, Menu_generate)) ;
  111. Notify_value canvas_proc           P((Xv_window, Event *,
  112.                                       Notify_arg, Notify_event_type)) ;
  113. void button_do                     P((Panel_item, Event *)) ;
  114. void canvas_resize_proc            P((Canvas, int, int)) ;
  115. void destroy_reve                  P(()) ;
  116. void reset_props                   P((Panel_item, Event *)) ;
  117. void set_depth                     P((Panel_item, int, Event *)) ;
  118. void set_profmax                   P((Panel_item, Event *)) ;
  119. void set_props                     P((Panel_item, Event *)) ;
  120. void xv_start_load                 P((Panel_item, Event *)) ;
  121. void xv_start_save                 P((Panel_item, Event *)) ;
  122.  
  123. static void change_depth           P((int)) ;
  124. static void connect_to_reve        P((int)) ;
  125. static void load_colors            P(()) ;
  126. static void set_interval_timer     P(()) ;
  127.  
  128.  
  129. void
  130. batch(state)            /* Turn graphics batching on or off. */
  131. enum bltype state ;
  132. {
  133.   XSync(dpy, 0) ;
  134. }
  135.  
  136.  
  137. void
  138. beep()
  139. {
  140.   XBell(dpy, 56) ;
  141.   XFlush(dpy) ;
  142. }
  143.  
  144.  
  145. /*ARGSUSED*/
  146. void
  147. button_do(item, event)
  148. Panel_item item ;
  149. Event *event ;
  150. {
  151.   char *label ;
  152.  
  153.   label = (char *) xv_get(item, PANEL_LABEL_STRING) ;
  154.        if (EQUAL(label, "Help..."))
  155.     position_popup(Reve_Wmain->Wmain, Reve_Whelp->Whelp, P_RIGHT) ;
  156.   else if (EQUAL(label, "Props..."))
  157.     position_popup(Reve_Wmain->Wmain, Reve_Wprops->Wprops, P_RIGHT) ;
  158. }
  159.  
  160.  
  161. /*ARGSUSED*/
  162. Notify_value
  163. canvas_proc(win, event, arg, type)
  164. Xv_window win ;
  165. Event *event ;
  166. Notify_arg arg ;
  167. Notify_event_type type ;
  168. {
  169.   cur_event = event ;     /* Determine what kind of event it is. */
  170.   handle_event() ;        /* And do the appropriate action. */
  171.   update_clock(next_player, FALSE) ;
  172.   return(notify_next_event_func(win, (Notify_event) event, arg, type)) ;
  173. }
  174.  
  175.  
  176. void
  177. canvas_resize_proc(canvas, width, height)
  178. Canvas canvas ;
  179. int width, height ;
  180. {
  181.   width  = (int) xv_get(Reve_Wboard->Bcanvas, XV_WIDTH) ;
  182.   height = (int) xv_get(Reve_Wboard->Bcanvas, XV_HEIGHT) ;
  183.   if (board_width != width || board_height != height)
  184.     {
  185.       board_width  = width ;
  186.       board_height = height ;
  187.       make_pieces(board_width, board_height) ;
  188.       paint_board() ;
  189.     }
  190. }
  191.  
  192.  
  193. static void
  194. change_depth(depth)
  195. int depth ;
  196. {
  197.   struct reve_in in ;
  198.  
  199.   in.type = M_PROFMAX ;
  200.   in.level = depth ;
  201.   WRITE(pipe_io[0][1], (char *) &in, sizeof(struct reve_in)) ;
  202. }
  203.  
  204.  
  205. static Notify_value
  206. check_clock(client, itimer_type)
  207. Notify_client client ;
  208. int itimer_type ;
  209. {
  210.   update_clock(next_player, FALSE) ;
  211.   return(NOTIFY_DONE) ;
  212. }
  213.  
  214.  
  215. void
  216. close_reve()
  217. {
  218.   XV_SET(Reve_Wboard->Wboard, FRAME_CLOSED, TRUE, 0) ;
  219. }
  220.  
  221.  
  222. /*ARGSUSED*/
  223. void
  224. color_area(wtype, x, y, width, height, color)
  225. enum win_type wtype ;
  226. int x, y, width, height, color ;
  227. {
  228.   if (iscolor) gc_val.foreground = palette[color] ;
  229.   else
  230.     { 
  231.       if (color == C_WHITE) gc_val.foreground = backgnd ;
  232.       else gc_val.foreground = foregnd ;
  233.     }
  234.   gc_val.function = GXcopy ;
  235.   gc_mask = GCForeground | GCFunction ;
  236.   XChangeGC(dpy, gc, gc_mask, &gc_val) ;
  237.   XFillRectangle(dpy, xid, gc,
  238.                  x, y, (unsigned int) width, (unsigned int) height) ;
  239. }
  240.  
  241.  
  242. void
  243. connect_io()    /* Connect to computer process and possible remote human. */
  244. {
  245.   if (pipe_io[1][0] > 0)
  246.     notify_set_input_func(client, read_from_fd, pipe_io[1][0]) ;
  247.   if (socketfd > 0)
  248.     notify_set_input_func(client, read_from_fd, socketfd) ;
  249.   notify_set_wait3_func(client, sigchldcatcher, pid) ;
  250. }
  251.  
  252.  
  253. void
  254. destroy_reve(item, event)          /* Terminate Reve. */
  255. Panel_item item ;
  256. Event *event ;
  257. {
  258.   xv_destroy_safe(Reve_Wmain->Wmain) ;
  259.   KILL(pid, SIGKILL) ;
  260.   exit(0) ;
  261. }
  262.  
  263.  
  264. /*ARGSUSED*/
  265. void
  266. draw_image(wtype, x, y, width, height, image)
  267. enum win_type wtype ;
  268. int x, y, width, height ;
  269. enum image_type image ;
  270. {
  271.   gc_mask = GCStipple | GCTileStipXOrigin | GCTileStipYOrigin ;
  272.   gc_val.stipple = images[(int) image] ;
  273.   gc_val.ts_x_origin = x ;
  274.   gc_val.ts_y_origin = y ;
  275.   XChangeGC(dpy, ropgc, gc_mask, &gc_val) ;
  276.   XFillRectangle(dpy, xid, ropgc, x, y, width, height) ;
  277. }
  278.  
  279.  
  280. /*ARGSUSED*/
  281. void
  282. draw_line(wtype, x1, y1, x2, y2, op, color)
  283. enum win_type wtype ;
  284. int x1, y1, x2, y2, color ;
  285. enum optype op ;
  286. {
  287.   if (iscolor) gc_val.foreground = palette[color] ;
  288.   else
  289.     { 
  290.       if (color == C_WHITE) gc_val.foreground = backgnd ;
  291.       else                  gc_val.foreground = foregnd ;
  292.     }
  293.   gc_val.function = opvals[(int) op] ;
  294.   XChangeGC(dpy, gc, GCForeground | GCFunction, &gc_val) ;
  295.   XDrawLine(dpy, xid, gc, x1, y1, x2, y2) ;
  296. }
  297.  
  298.  
  299. /*ARGSUSED*/
  300. void
  301. draw_stencil(wtype, x, y, width, height, op, color, stencil, image)
  302. enum win_type wtype ;
  303. int x, y, width, height, color ;
  304. enum optype op ;
  305. enum image_type stencil, image ;
  306. {
  307.   if (iscolor) gc_val.foreground = palette[color] ;
  308.   else            gc_val.foreground = foregnd ;
  309.   gc_val.function = opvals[(int) op] ;
  310.   gc_val.clip_x_origin = x ;
  311.   gc_val.clip_y_origin = y ;
  312.   gc_val.clip_mask = images[(int) stencil] ;
  313.   gc_val.stipple = images[(int) image] ;
  314.   gc_val.ts_x_origin = x ;
  315.   gc_val.ts_y_origin = y ;
  316.   gc_mask = GCForeground | GCFunction | GCClipMask |
  317.             GCClipXOrigin | GCClipYOrigin |
  318.             GCStipple | GCTileStipXOrigin | GCTileStipYOrigin ;
  319.   XChangeGC(dpy, stencilgc, gc_mask, &gc_val) ;
  320.   XFillRectangle(dpy, xid, stencilgc, x, y, width, height) ;
  321. }
  322.  
  323.  
  324. /*ARGSUSED*/
  325. void
  326. draw_text(wtype, x, y, ftype, color, str)
  327. enum win_type wtype ;
  328. enum font_type ftype ;
  329. int x, y, color ;
  330. char *str ;
  331. {
  332.   if (iscolor) gc_val.foreground = palette[color] ;
  333.   else
  334.     {
  335.       if (color == C_WHITE) gc_val.foreground = backgnd ;
  336.       else gc_val.foreground = foregnd ;
  337.     }
  338.   gc_val.font = font[(int) ftype]->fid ;
  339.   gc_val.function = GXcopy ;
  340.   XChangeGC(dpy, gc, GCFont | GCForeground | GCFunction, &gc_val) ;
  341.   XDrawString(dpy, xid, gc, x, y, str, strlen(str)) ;
  342. }
  343.  
  344.  
  345. static XFontStruct *
  346. get_font(name, defname)
  347. char *name, *defname ;
  348. {
  349.   XFontStruct *f ;
  350.  
  351.   if (name == NULL || !(f = XLoadQueryFont(dpy, name)))
  352.     if (!(f = XLoadQueryFont(dpy, defname)))
  353.       if (!(f = XLoadQueryFont(dpy, DEFFONT)))
  354.         {
  355.           FPRINTF(stderr, "%s: couldn't get the default font.", progname) ;
  356.           exit(1) ;
  357.         }
  358.   return(f) ;
  359. }
  360.  
  361.  
  362. char *
  363. get_resource(rtype)      /* Get Reve resource from merged databases. */
  364. enum res_type rtype ;
  365. {
  366.   char cstr[MAXLINE], nstr[MAXLINE], str[MAXLINE] ;
  367.   char *str_type[20] ;
  368.   XrmValue value ;
  369.  
  370.   STRCPY(str, resources[(int) rtype]) ;
  371.   SPRINTF(nstr,  "reve.%s", str) ;
  372.   if (islower(str[0])) str[0] = toupper(str[0]) ;
  373.   SPRINTF(cstr, "Reve.%s", str) ;
  374.   if (XrmGetResource(reve_DB, nstr, cstr, str_type, &value) == NULL)
  375.     return((char *) NULL) ;
  376.   else return(value.addr) ;
  377. }
  378.  
  379.  
  380. int
  381. get_strwidth(ftype, str)    /* Get width in pixels of string value. */
  382. enum font_type ftype ;
  383. char *str ;
  384. {
  385.   return(XTextWidth(font[(int) ftype], str, strlen(str))) ;
  386. }
  387.  
  388.  
  389. void
  390. init_fonts()         /* Open the normal and bold fonts. */
  391. {
  392.   int i ;
  393.  
  394.   font[(int) BFONT] = get_font(fontnames[(int) BFONT], BOLDFONT) ;
  395.   font[(int) GFONT] = get_font(fontnames[(int) GFONT], BOARDFONT) ;
  396.   font[(int) HFONT] = get_font(fontnames[(int) HFONT], HELPFONT) ;
  397.   font[(int) NFONT] = get_font(fontnames[(int) NFONT], NORMALFONT) ;
  398.  
  399.   for (i = 0; i < MAXFONTS; i++)
  400.     font_heights[i] = font[i]->max_bounds.ascent +
  401.                       font[i]->max_bounds.descent ;
  402. }
  403.  
  404.  
  405. void
  406. init_graphics(argc, argv)
  407. int *argc ;
  408. char *argv[] ;
  409. {
  410.   xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL) ;
  411.   INSTANCE = xv_unique_key() ;
  412.  
  413.   Reve_Wmain  = reve_Wmain_objects_initialize(NULL, NULL) ;
  414.   Reve_Wdepth = reve_Wdepth_objects_initialize(NULL, Reve_Wmain->Wmain) ;
  415.   Reve_Wprops = reve_Wprops_objects_initialize(NULL, Reve_Wmain->Wmain) ;
  416.   Reve_Whelp  = reve_Whelp_objects_initialize(NULL, Reve_Wmain->Wmain) ;
  417.   Reve_Wload  = reve_Wload_objects_initialize(NULL, Reve_Wmain->Wmain) ;
  418.   Reve_Wsave  = reve_Wsave_objects_initialize(NULL, Reve_Wmain->Wmain) ;
  419.   Reve_Wboard = reve_Wboard_objects_initialize(NULL, NULL) ;
  420.  
  421.   dpy     = (Display *) xv_get(Reve_Wmain->Wmain, XV_DISPLAY) ;
  422.   reve_DB = NULL ;
  423.   igc     = NULL ;
  424. }
  425.  
  426.  
  427. int
  428. init_ws_type()
  429. {
  430.   gtype      = GXVIEW ;        /* Graphics type. */
  431.   move_delta = 10 ;
  432.   if (xdebug == TRUE) XSynchronize(dpy, TRUE) ;
  433.   return(0) ;
  434. }
  435.  
  436.  
  437. static void
  438. load_colors()      /* Create and load reve color map. */
  439. {
  440.   XColor ccol ;
  441.   int i, numcolors ;
  442.  
  443.   if (iscolor)
  444.     {
  445.       numcolors = 0 ;
  446.       for (i = 0; i < REVE_USEDCOLORSIZE; i++)
  447.         {
  448.           if (colstr[i] == NULL ||
  449.               (XParseColor(dpy, DefaultColormap(dpy, screen),
  450.                            colstr[i], &ccol) == 0)) 
  451.             {
  452.               ccol.flags = DoRed | DoGreen | DoBlue ;
  453.               ccol.red   = (unsigned short) (rcols[i] << 8) ;
  454.               ccol.green = (unsigned short) (gcols[i] << 8) ;
  455.               ccol.blue  = (unsigned short) (bcols[i] << 8) ;
  456.             }
  457.           if (XAllocColor(dpy, DefaultColormap(dpy, screen), &ccol) == True)
  458.             palette[numcolors++] = ccol.pixel ;
  459.         }
  460.       if (numcolors < REVE_USEDCOLORSIZE)
  461.         {
  462.           FPRINTF(stderr, "%s: cannot allocate colors.\n", progname) ;
  463.           exit(1) ;
  464.         }
  465.     }
  466. }
  467.  
  468.  
  469. /*  Get the resource databases. These are looked for in the following ways:
  470.  *
  471.  *  Classname file in the app-defaults directory. In this case, Classname
  472.  *  is Reve.
  473.  *
  474.  *  Classname file in the directory specified by the XUSERFILESEARCHPATH
  475.  *  or XAPPLRESDIR environment variable.
  476.  *
  477.  *  Property set using xrdb, accessible through the XResourceManagerString
  478.  *  macro or, if that is empty, the ~/.Xdefaults file.
  479.  *
  480.  *  XENVIRONMENT environment variable or, if not set, .Xdefaults-hostname
  481.  *  file.
  482.  *
  483.  *  REVEDEFAULTS environment variable or, if not set, the ~/.reverc file.
  484.  */
  485.  
  486. void
  487. load_resources()
  488. {
  489.   XrmDatabase db ;
  490.   char *home, name[MAXPATHLEN], *ptr ;
  491.   int len ;
  492.  
  493.   home = getenv("HOME") ;
  494.   XrmInitialize() ;
  495.   STRCPY(name, "/usr/lib/X11/app-defaults/Reve") ;
  496.  
  497. /* Get applications defaults file, if any. */
  498.  
  499.   db = XrmGetFileDatabase(name) ;
  500.   XrmMergeDatabases(db, &reve_DB) ;
  501.  
  502. /* Merge server defaults, created by xrdb. If nor defined, use ~/.Xdefaults. */
  503.  
  504.   if (XResourceManagerString(dpy) != NULL)
  505.     db = XrmGetStringDatabase(XResourceManagerString(dpy)) ;
  506.   else
  507.     { 
  508.       SPRINTF(name, "%s/.Xdefaults", home) ;
  509.       db = XrmGetFileDatabase(name) ;
  510.     }
  511.   XrmMergeDatabases(db, &reve_DB) ;
  512.  
  513. /*  Open XENVIRONMENT file or, if not defined, the .Xdefaults, and merge
  514.  *  into existing database.
  515.  */
  516.  
  517.   if ((ptr = getenv("XENVIRONMENT")) == NULL)
  518.     {
  519.       SPRINTF(name, "%s/.Xdefaults-", home) ;
  520.       len = strlen(name) ;
  521.       GETHOSTNAME(name+len, MAXPATHLEN-len) ;
  522.       db = XrmGetFileDatabase(name) ;
  523.     }
  524.   else db = XrmGetFileDatabase(ptr) ;
  525.   XrmMergeDatabases(db, &reve_DB) ;
  526.  
  527. /*  Finally merge in Reve defaults via REVEDEFAULTS or, if not defined, the
  528.  *  ~/.reverc file.
  529.  */
  530.   
  531.   if ((ptr = getenv("REVEDEFAULTS")) == NULL)
  532.     {
  533.       SPRINTF(name, "%s/.reverc", home) ;
  534.       db = XrmGetFileDatabase(name) ;
  535.     }
  536.   else db = XrmGetFileDatabase(ptr) ;
  537.   XrmMergeDatabases(db, &reve_DB) ;
  538. }
  539.  
  540.  
  541. void
  542. lock_screen(state)
  543. enum bltype state ;
  544. {}
  545.  
  546.  
  547. void
  548. make_canvas()               /* Create canvas for game board. */
  549. {
  550.   gpw = canvas_paint_window(Reve_Wboard->Bcanvas) ;
  551.   XV_SET(canvas_paint_window(Reve_Wboard->Bcanvas),
  552.          WIN_CONSUME_EVENTS,
  553.            KBD_USE, KBD_DONE, LOC_DRAG,
  554.            WIN_LEFT_KEYS, WIN_TOP_KEYS, WIN_RIGHT_KEYS,
  555.            0,
  556.          0) ;
  557.   cursor[(int) CANVASCUR] = xv_get(gpw, WIN_CURSOR) ;
  558.  
  559.   xid     = (Drawable) xv_get(gpw, XV_XID) ;
  560.   screen  = DefaultScreen(dpy) ;
  561.   root    = RootWindow(dpy, screen) ;
  562.   foregnd = BlackPixel(dpy, screen) ;
  563.   backgnd = WhitePixel(dpy, screen) ;
  564.  
  565.   gc_mask           = GCForeground | GCBackground | GCGraphicsExposures ;
  566.   gc_val.foreground = foregnd ;
  567.   gc_val.background = backgnd ;
  568.   gc_val.graphics_exposures = False ;
  569.   gc = XCreateGC(dpy, root, gc_mask, &gc_val) ;
  570.  
  571.   ropgc = XCreateGC(dpy, root, gc_mask, &gc_val) ;
  572.   XSetFillStyle(dpy, ropgc, FillStippled) ;
  573.  
  574.   stencilgc = XCreateGC(dpy, root, gc_mask, &gc_val) ;
  575.   XSetFillStyle(dpy, stencilgc, FillOpaqueStippled) ;
  576.  
  577.   hglass_pr = xv_create(XV_NULL,             SERVER_IMAGE,
  578.                         XV_WIDTH,            16,
  579.                         XV_HEIGHT,           16,
  580.                         SERVER_IMAGE_X_BITS, hglass_bits,
  581.                         0) ;
  582.   cursor[(int) HOURGLASS] = xv_create(XV_NULL,      CURSOR,
  583.                                       CURSOR_IMAGE, hglass_pr,
  584.                                       0) ;
  585.   nocur_pr = xv_create(XV_NULL,             SERVER_IMAGE,
  586.                        XV_WIDTH,            16,
  587.                        XV_HEIGHT,           16,
  588.                        SERVER_IMAGE_X_BITS, nocur_bits,
  589.                        0) ;
  590.   cursor[(int) NOCURSOR] = xv_create(XV_NULL,      CURSOR,
  591.                                      CURSOR_IMAGE, nocur_pr,
  592.                                      0) ;
  593.   if (!monochrome) load_colors() ;
  594.  
  595.   images[(int) P_WHITE]     = make_server_image(white_bits) ;
  596.   images[(int) P_BLACK]     = make_server_image(black_bits) ;
  597.   images[(int) S_MOVE]      = make_server_image(move_bits) ;
  598.   images[(int) S_SUGGEST]   = make_server_image(suggest_bits) ;
  599.  
  600.   pid = fork_child() ;
  601. }
  602.  
  603.  
  604. /*ARGSUSED*/
  605. void 
  606. make_frame(argc, argv)     /* Create frame and the panel, buttons, menus. */
  607. int argc ;
  608. char *argv[] ;
  609. {
  610.   char mes[MAXLINE] ;
  611.   int val ;
  612.  
  613.   opvals[(int) RCLR] = GXclear ;
  614.   opvals[(int) RSRC] = GXcopy ;
  615.   opvals[(int) RINV] = GXxor ;
  616.  
  617.   XV_SET(Reve_Wboard->Wboard, XV_WIDTH,  board_width, 0) ;
  618.   XV_SET(Reve_Wboard->Wboard, XV_HEIGHT, board_height, 0) ;
  619.  
  620.   SPRINTF(mes, "%s:", bstone_name) ;
  621.   XV_SET(Reve_Wmain->Tblack, PANEL_LABEL_STRING, mes, 0) ;
  622.   val = items[(int) BLACK_PLAYS].value ;
  623.   XV_SET(Reve_Wmain->Tblack, PANEL_VALUE, player_values[val], 0) ;
  624.  
  625.   SPRINTF(mes, "%s:", wstone_name) ;
  626.   XV_SET(Reve_Wmain->Twhite, PANEL_LABEL_STRING, mes, 0) ;
  627.   val = items[(int) WHITE_PLAYS].value ;
  628.   XV_SET(Reve_Wmain->Twhite, PANEL_VALUE, player_values[val], 0) ;
  629.  
  630.   SPRINTF(mes, "%s to move", bstone_name) ;
  631.   XV_SET(Reve_Wmain->Mturn, PANEL_LABEL_STRING, mes, 0) ;
  632.  
  633.   XV_SET(Reve_Wload->Tload, PANEL_VALUE, gamefile, 0) ;
  634.   XV_SET(Reve_Wsave->Tsave, PANEL_VALUE, gamefile, 0) ;
  635.  
  636.        if (dtype == XBLACK) val = CP_WHITE ;
  637.   else if (dtype == XWHITE) val = CP_BLACK ;
  638.   else if (dtype == XBOTH)  val = CP_NEITHER ;
  639.  
  640.   XV_SET(Reve_Wprops->Splays, PANEL_CHOICE_STRING, 0, wstone_name, 0) ;
  641.   XV_SET(Reve_Wprops->Splays, PANEL_CHOICE_STRING, 1, bstone_name, 0) ;
  642.   XV_SET(Reve_Wprops->Splays, PANEL_VALUE, val, 0) ;
  643.  
  644.   XV_SET(Reve_Wprops->Sdifficulty,
  645.          PANEL_VALUE, items[(int) DIFF_CHOICE].value,
  646.          0) ;
  647.  
  648.   val = ((ANIMATION   & 0x1) << 0) +
  649.         ((DO_BESTMOVE & 0x1) << 1) +
  650.         ((DO_LAST     & 0x1) << 2) +
  651.         ((SHOW_NOTES  & 0x1) << 3) +
  652.         ((DO_NUMBER   & 0x1) << 4) +
  653.         ((QUICKGAME   & 0x1) << 5) +
  654.         ((SHOW_LEGAL  & 0x1) << 6) +
  655.         ((DO_CLOCK    & 0x1) << 7) ;
  656.   XV_SET(Reve_Wprops->Soptions, PANEL_VALUE, val, 0) ;
  657.  
  658.   XV_SET(Reve_Wmain->Tblack_time,
  659.          PANEL_LABEL_BOLD, FALSE,
  660.          PANEL_VALUE,      items[(int) BLACK_CLOCK].text,
  661.          XV_SHOW,          DO_CLOCK,
  662.          0) ;
  663.  
  664.   XV_SET(Reve_Wmain->Twhite_time,
  665.          PANEL_LABEL_BOLD, FALSE,
  666.          PANEL_VALUE,      items[(int) WHITE_CLOCK].text,
  667.          XV_SHOW,          DO_CLOCK,
  668.          0) ;
  669.  
  670.   iscolor = ((int) xv_get(Reve_Wmain->Wmain, WIN_DEPTH) > 1) ? 1 : 0 ;
  671. }
  672.  
  673.  
  674. /*ARGSUSED*/
  675. void
  676. make_help_window(argc, argv)
  677. int argc ;
  678. char *argv[] ;
  679. {
  680.   XV_SET(Reve_Whelp->Whelp, XV_SHOW, help_showing, 0) ;
  681.   XV_SET(Reve_Whelp->textpane1,
  682.          TEXTSW_FILE_CONTENTS,  helpfile,
  683.          TEXTSW_READ_ONLY,      TRUE,
  684.          TEXTSW_FIRST,          0,
  685.          TEXTSW_BROWSING,       TRUE,
  686.          0) ;
  687. }
  688.  
  689.  
  690. void
  691. make_icon()
  692. {}
  693.  
  694.  
  695. void
  696. make_pieces(width, height)
  697. int width, height ;
  698. {
  699.   bborder = BBORDER ;
  700.  
  701.   cell_width   = (width  - (2 * bborder)) / BOARD_SIZE ;
  702.   cell_height  = (height - (2 * bborder)) / BOARD_SIZE ;
  703.  
  704.   pieceXmargin = cell_width  / 8 ;
  705.   pieceYmargin = cell_height / 8 ;
  706.  
  707.   pieceXrad = (cell_width  - (2 * pieceXmargin)) / 2 ;
  708.   if (pieceXrad > MAXPRAD)
  709.     {
  710.       pieceXrad    = MAXPRAD ;
  711.       pieceXmargin = (cell_width - (2 * pieceXrad)) / 2 ;
  712.     }
  713.  
  714.   pieceYrad = (cell_height - (2 * pieceYmargin)) / 2 ;
  715.   if (pieceYrad > MAXPRAD)
  716.     {
  717.       pieceYrad    = MAXPRAD ;
  718.       pieceYmargin = (cell_height - (2 * pieceYrad)) / 2 ;
  719.     }
  720.  
  721.   if (igc == NULL)
  722.     {
  723.       gc_mask = GCForeground | GCBackground | GCGraphicsExposures ;
  724.       gc_val.foreground = foregnd ;
  725.       gc_val.background = backgnd ;
  726.       gc_val.graphics_exposures = False ;
  727.       igc = XCreateGC(dpy, images[(int) P_WHITE], gc_mask, &gc_val) ;
  728.     }
  729.  
  730.   XSetFunction(dpy, igc, GXclear) ;
  731.   XCopyArea(dpy, images[(int) P_WHITE], images[(int) P_WHITE], igc,
  732.             0, 0, 2 * MAXPRAD, 2 * MAXPRAD, 0, 0) ;
  733.   XCopyArea(dpy, images[(int) P_BLACK], images[(int) P_BLACK], igc,
  734.             0, 0, 2 * MAXPRAD, 2 * MAXPRAD, 0, 0) ;
  735.  
  736.   XSetFunction(dpy, igc, GXcopy) ;
  737.   XDrawArc(dpy, images[(int) P_WHITE], igc,
  738.            0, 0, 2 * pieceXrad - 1, 2 * pieceYrad - 1, 0, 360 * 64) ;
  739.   XFillArc(dpy, images[(int) P_BLACK], igc,
  740.            0, 0, 2 * pieceXrad - 1, 2 * pieceYrad - 1, 0, 360 * 64) ;
  741. }
  742.  
  743.  
  744. static Drawable
  745. make_server_image(image)
  746. unsigned char *image ;
  747. {
  748.   Server_image temp ;
  749.  
  750.   temp = xv_create(XV_NULL,             SERVER_IMAGE,
  751.                    XV_WIDTH,            64,
  752.                    XV_HEIGHT,           64,
  753.                    SERVER_IMAGE_X_BITS, image,
  754.                    0) ;
  755.   return((int) xv_get(temp, XV_XID, NULL)) ;
  756. }
  757.  
  758.  
  759. Menu_item
  760. menu_do(item, op)
  761. Menu_item item ;
  762. Menu_generate op ;
  763. {
  764.   char *label ;
  765.  
  766.   if (op == MENU_NOTIFY)
  767.     {
  768.       label = (char *) xv_get(item, MENU_STRING) ;
  769.            if (EQUAL(label, "New"))      new_game() ;
  770.       else if (EQUAL(label, "Print"))    print_game() ;
  771.       else if (EQUAL(label, "Load..."))
  772.         position_popup(Reve_Wmain->Wmain, Reve_Wload->Wload, P_RIGHT) ;
  773.       else if (EQUAL(label, "Save..."))
  774.         position_popup(Reve_Wmain->Wmain, Reve_Wsave->Wsave, P_RIGHT) ;
  775.  
  776.       else if (EQUAL(label, "Redo"))     redo() ;
  777.       else if (EQUAL(label, "Show All")) show_all_moves() ;
  778.       else if (EQUAL(label, "Suggest"))  suggest() ;
  779.       else if (EQUAL(label, "Undo"))     undo() ;
  780.     }
  781.   return(item) ;
  782. }
  783.  
  784.  
  785. void
  786. open_reve()
  787. {
  788.   XV_SET(Reve_Wboard->Wboard, FRAME_CLOSED, FALSE, 0) ;
  789. }
  790.  
  791.  
  792. void
  793. position_popup(parent, child, position)
  794. Frame parent, child ;
  795. int position ;
  796. {
  797.   Rect crect, prect ;
  798.   int height, width ;
  799.  
  800.   if (((int) xv_get(child, XV_SHOW)) && position == P_RIGHT) return ;
  801.   frame_get_rect(parent, &prect) ;
  802.   frame_get_rect(child,  &crect) ;
  803.   height = (int) xv_get(parent, XV_HEIGHT) ;
  804.   width  = (int) xv_get(parent, XV_WIDTH) ;
  805.  
  806.   switch (position)
  807.     {
  808.       case P_BELOW : crect.r_left = prect.r_left + FRAME_BORDER_SIZE ;
  809.                      crect.r_top  = prect.r_top + height + FRAME_LABEL_SIZE +
  810.                                     FRAME_BORDER_SIZE ;
  811.                      break ;
  812.       case P_RIGHT : crect.r_left = prect.r_left + width +
  813.                                                    (2 * FRAME_BORDER_SIZE) ;
  814.                      crect.r_top  = prect.r_top ;
  815.     }
  816.   frame_set_rect(child, &crect) ;
  817.   if (child != Reve_Wboard->Wboard)
  818.     XV_SET(child, FRAME_CMD_PUSHPIN_IN, TRUE, 0) ;
  819.   XV_SET(child, XV_SHOW, TRUE, 0) ;
  820. }
  821.  
  822.  
  823. void
  824. process_event()       /* Process the next canvas event. */
  825. {
  826.   int action, id ;
  827.  
  828.   nextc  = IGNORE_EVENT ;
  829.   action = event_action(cur_event) ;
  830.   id     = event_id(cur_event) ;
  831.   curx   = event_x(cur_event) ;
  832.   cury   = event_y(cur_event) ;
  833.  
  834.        if (id == KBD_DONE    || id == LOC_WINEXIT) nextc = EXIT_WINDOW ;
  835.   else if (id == LOC_WINENTER)                     nextc = ENTER_WINDOW ;
  836.   else if (id == LOC_DRAG)                         nextc = MOUSE_MOVING ;
  837.   else if (id == WIN_REPAINT)                      nextc = BOARD_REPAINT ;
  838.   else if (event_is_button(cur_event) && event_is_down(cur_event))
  839.     {
  840.            if (id == MS_LEFT)   nextc = LEFT_DOWN ;
  841.       else if (id == MS_MIDDLE) nextc = MIDDLE_DOWN ;
  842.       else if (id == MS_RIGHT)  nextc = RIGHT_DOWN ;
  843.     }
  844.   else if (event_is_button(cur_event) && event_is_up(cur_event))
  845.     {
  846.            if (id == MS_LEFT)   nextc = LEFT_UP ;
  847.       else if (id == MS_MIDDLE) nextc = MIDDLE_UP ;
  848.       else if (id == MS_RIGHT)  nextc = RIGHT_UP ;
  849.     }
  850.   else if (event_is_ascii(cur_event))
  851.     {
  852.       cur_ch = id ;
  853.       nextc = KEYBOARD ;
  854.     }
  855.   else if (action == ACTION_PROPS && event_is_down(cur_event))
  856.     position_popup(Reve_Wmain->Wmain, Reve_Wprops->Wprops, P_RIGHT) ;
  857. }
  858.  
  859.  
  860. /*ARGSUSED*/
  861. static Notify_value
  862. quit_proc(client, status)
  863. Notify_client client ;
  864. Destroy_status status ;
  865. {
  866.   destroy_reve() ;
  867. }
  868.  
  869.  
  870. void
  871. raise_reve()
  872. {
  873.   wmgr_top(Reve_Wboard->Wboard) ;
  874. }
  875.  
  876.  
  877. static Notify_value
  878. read_from_fd(client, fd)
  879. Notify_client client ;
  880. register int fd ;
  881. {
  882.        if (fd == socketfd) read_from_sock(fd) ;          /* Remote human. */
  883.   else if (fd == pipe_io[1][0]) read_from_reve(fd) ;     /* Computer. */
  884.   set_interval_timer() ;
  885.   return(NOTIFY_DONE) ;
  886. }
  887.  
  888.  
  889. /*ARGSUSED*/
  890. void
  891. reset_props(item, event)
  892. Panel_item item ;
  893. Event *event ;
  894. {
  895.   int val ;
  896.  
  897.        if (dtype == XBLACK) val = CP_WHITE ;
  898.   else if (dtype == XWHITE) val = CP_BLACK ;
  899.   else if (dtype == XBOTH)  val = CP_NEITHER ;
  900.   XV_SET(Reve_Wprops->Splays, PANEL_VALUE, val, 0) ;
  901.  
  902.   val = ((ANIMATION   & 0x1) << 0) +
  903.         ((DO_BESTMOVE & 0x1) << 1) +
  904.         ((DO_LAST     & 0x1) << 2) +
  905.         ((SHOW_NOTES  & 0x1) << 3) +
  906.         ((DO_NUMBER   & 0x1) << 4) +
  907.         ((QUICKGAME   & 0x1) << 5) +
  908.         ((SHOW_LEGAL  & 0x1) << 6) +
  909.         ((DO_CLOCK    & 0x1) << 7) ;
  910.   XV_SET(Reve_Wprops->Soptions, PANEL_VALUE, val, 0) ;
  911. }
  912.  
  913.  
  914. void
  915. set_cursor(ctype)
  916. enum curtype ctype ;
  917. {
  918.   if (ctype == NOCURSOR) return ;
  919.   XV_SET(gpw,    WIN_CURSOR, cursor[(int) ctype], 0) ;
  920.   XV_SET(Reve_Wmain->controls1,  WIN_CURSOR, cursor[(int) ctype], 0) ;
  921.   XV_SET(Reve_Wprops->controls4, WIN_CURSOR, cursor[(int) ctype], 0) ;
  922. }
  923.  
  924.  
  925. void 
  926. set_depth(item, value, event)
  927. Panel_item item ;
  928. int value ;
  929. Event *event ;
  930. {
  931.   position_popup(Reve_Wmain->Wmain, Reve_Wdepth->Wdepth, P_RIGHT) ;
  932. }
  933.  
  934.  
  935. /*ARGSUSED*/
  936. void
  937. set_frame(wtype, showing)
  938. enum win_type wtype ;
  939. int showing ;
  940. {}
  941.  
  942.  
  943. static void
  944. set_interval_timer()
  945. {
  946.   struct itimerval tval ;
  947.  
  948.   tval.it_interval.tv_usec = 0 ;     /* Force a timing check every second. */
  949.   tval.it_interval.tv_sec  = 1 ;
  950.   tval.it_value.tv_usec    = 0 ;
  951.   tval.it_value.tv_sec     = 1 ;
  952.   notify_set_itimer_func(Reve_Wboard->Wboard, check_clock, ITIMER_REAL,
  953.                          &tval, (struct itimerval *) 0) ;
  954. }
  955.  
  956.  
  957. void
  958. set_profmax(item, event)
  959. Panel_item item ;
  960. Event *event ;
  961. {
  962.   change_depth((int) xv_get(Reve_Wdepth->Tdepth, PANEL_VALUE)) ;
  963.   level = 1 ;
  964. }
  965.  
  966.  
  967. /*ARGSUSED*/
  968. void
  969. set_props(item, event)
  970. Panel_item item ;
  971. Event *event ;
  972. {
  973.   int curi, oldval, val ;
  974.  
  975.        if (dtype == XBLACK) oldval = CP_WHITE ;
  976.   else if (dtype == XWHITE) oldval = CP_BLACK ;
  977.   else if (dtype == XBOTH)  oldval = CP_NEITHER ;
  978.  
  979.   val = (int) xv_get(Reve_Wprops->Splays, PANEL_VALUE, 0) ;
  980.   if (val == CP_WHITE)
  981.     {
  982.       dtype = XBLACK ;
  983.       play_computer = TRUE ;
  984.       items[(int) BLACK_PLAYS].value = HUMAN ; 
  985.       items[(int) WHITE_PLAYS].value = COMPUTER ;
  986.     }
  987.   else if (val == CP_BLACK)
  988.     {
  989.       dtype = XWHITE ;
  990.       play_computer = TRUE ;
  991.       items[(int) BLACK_PLAYS].value = COMPUTER ;
  992.       items[(int) WHITE_PLAYS].value = HUMAN ;
  993.  
  994.     }
  995.   else if (val == CP_NEITHER)
  996.     {
  997.       dtype = XBOTH ;
  998.       play_computer = FALSE ;
  999.       items[(int) BLACK_PLAYS].value = HUMAN ;
  1000.       items[(int) WHITE_PLAYS].value = HUMAN ;
  1001.     }
  1002.   else if (val == CP_BOTH)
  1003.     {
  1004.       XV_SET(Reve_Wprops->Splays, PANEL_VALUE, oldval, 0) ;
  1005.       message(PANEL_MES, "Computer plays both is not implemented yet.") ;
  1006.     }
  1007.  
  1008.   val = items[(int) BLACK_PLAYS].value ;
  1009.   XV_SET(Reve_Wmain->Tblack, PANEL_VALUE, player_values[val], 0) ;
  1010.   val = items[(int) WHITE_PLAYS].value ;
  1011.   XV_SET(Reve_Wmain->Twhite, PANEL_VALUE, player_values[val], 0) ;
  1012.  
  1013.   if (next_player == BLACK) curi = items[(int) BLACK_PLAYS].value ;
  1014.   else                      curi = items[(int) WHITE_PLAYS].value ;
  1015.   if (curi == COMPUTER)
  1016.     if ((next_player == BLACK && cmode == BLACK_START) ||
  1017.         (next_player == WHITE && cmode == WHITE_START))
  1018.       opponent_move(next_player) ;
  1019.  
  1020.   val = (int) xv_get(Reve_Wprops->Soptions, PANEL_VALUE, 0) ;
  1021.   ANIMATION   = (val >> 0) & 0x1 ;
  1022.   DO_BESTMOVE = (val >> 1) & 0x1 ;
  1023.   DO_LAST     = (val >> 2) & 0x1 ;
  1024.   SHOW_NOTES  = (val >> 3) & 0x1 ;
  1025.   DO_NUMBER   = (val >> 4) & 0x1 ;
  1026.   QUICKGAME   = (val >> 5) & 0x1 ;
  1027.   SHOW_LEGAL  = (val >> 6) & 0x1 ;
  1028.   DO_CLOCK    = (val >> 7) & 0x1 ;
  1029.  
  1030.   XV_SET(Reve_Wmain->Tblack_time, XV_SHOW, DO_CLOCK, 0) ;
  1031.   XV_SET(Reve_Wmain->Twhite_time, XV_SHOW, DO_CLOCK, 0) ;
  1032.  
  1033.   XV_SET(Reve_Wprops->Wprops, XV_SHOW, FALSE, 0) ;
  1034. }
  1035.  
  1036.  
  1037. static Notify_value
  1038. sigchldcatcher(client, pid, status, rusage)
  1039. Notify_client client ;
  1040. int pid ;
  1041. union wait *status ;
  1042. struct rusage *rusage ;
  1043. {
  1044.   if (WIFEXITED(*status))
  1045.     {
  1046.       notify_set_input_func(client, NOTIFY_FUNC_NULL, pipe_io[1][0]) ;
  1047.       return(NOTIFY_DONE) ;
  1048.     }
  1049.   return(NOTIFY_IGNORED) ;
  1050. }
  1051.  
  1052.  
  1053. /*ARGSUSED*/
  1054. void
  1055. start_tool(dtype)      /* Display window and start the notifier. */
  1056. enum disp_type dtype ;
  1057. {
  1058.   set_interval_timer() ;
  1059.   notify_interpose_destroy_func(Reve_Wmain->Wmain,   quit_proc) ;
  1060.   notify_interpose_destroy_func(Reve_Wboard->Wboard, quit_proc) ;
  1061.   xv_main_loop(Reve_Wmain->Wmain) ;
  1062. }
  1063.  
  1064.  
  1065. void
  1066. xv_clock(ptype)
  1067. enum panel_type ptype ;
  1068. {
  1069.   Xv_opaque handle ;
  1070.  
  1071.        if (ptype == BLACK_CLOCK) handle = Reve_Wmain->Tblack_time ;
  1072.   else if (ptype == WHITE_CLOCK) handle = Reve_Wmain->Twhite_time ;
  1073.   XV_SET(handle, PANEL_VALUE, items[(int) ptype].text, 0) ;
  1074. }
  1075.  
  1076.  
  1077. void
  1078. xv_message(mtype, str)
  1079. enum panel_type mtype ;
  1080. char *str ;
  1081. {
  1082.   Xv_opaque handle ;
  1083.  
  1084.        if (mtype == PANEL_MES) handle = Reve_Wmain->Mpanel ;
  1085.   else if (mtype == EVAL_MES)  handle = Reve_Wmain->Meval ;
  1086.   else if (mtype == SCORE_MES) handle = Reve_Wmain->Mscore ;
  1087.   else if (mtype == TURN_MES)  handle = Reve_Wmain->Mturn ;
  1088.   XV_SET(handle, PANEL_LABEL_STRING, str, 0) ;
  1089. }
  1090.  
  1091.  
  1092. void
  1093. xv_start_load(item, event)
  1094. Panel_item item ;
  1095. Event *event ;
  1096. {
  1097.   STRCPY(gamefile, (char *) xv_get(Reve_Wload->Tload, PANEL_VALUE)) ;
  1098.   load_game() ;
  1099. }
  1100.  
  1101.  
  1102. void
  1103. xv_start_save(item, event)
  1104. Panel_item item ;
  1105. Event *event ;
  1106. {
  1107.   STRCPY(gamefile, (char *) xv_get(Reve_Wsave->Tsave, PANEL_VALUE)) ;
  1108.   save_game() ;
  1109. }
  1110.